<template>
	<div class="index-bar">
		<scroll :bounce='false'
						:data='list'
						listen-scroll
						@scroll='scroll'
						stop-propagation
						ref="scroll"
		>
			<ul class="index-bar__list">
				<li v-for="(group, index) of list" :key="index" :ref="'group-' + index">
					<span class="index-bar__title">{{ group.title }}</span>
					<ul>
						<li v-for="(item, index) of group.items" :key="index" class="index-bar__listitem" :style="listitemStyle" @click="clickItem(item)">
							<slot :item='item'>{{ item.text }}</slot>
						</li>
					</ul>
				</li>
			</ul>
		</scroll>
		<span class="index-bar__title index-bar__fixed" ref="fixedTitle" :style="fixedTitleStyle">
			{{ fixedTitle }}
		</span>

		<div class="index-bar__sidebar" @touchstart='touchstart' @touchmove='touchmove'>
			<ul ref="sidebar">
				<li v-for="(group, index) of list"
						:key="index"
						:data-index='index'
						:class="index === activeIndex ? 'index-bar__sidebaritem--active' : ''"
						class="index-bar__sidebaritem"
				>{{ group.title }}</li>
			</ul>
		</div>
	</div>
</template>

<script>
import scroll from '@/base/scroll'
import { rangs } from '@/utils'

const ANCHOR_HEIGTH = 40

export default {
	components: {
		scroll
	},
	props: {
		list: {
			type: Array,
			default() {
				return []
			}
		}
	},
	computed: {
		fixedTitle() {
			return this.list[this.activeIndex].title
		},
		fixedTitleHeight() {
			return this.$refs.fixedTitle.offsetHeight
		},
		fixedTitleStyle() {
			return {
				transform: `translateY(${this.transformY}px)`
			}
		},
		len() {
			return this.groupHeights.length
		},
		sidebarItemHeight() {
			return this.$refs.sidebar.offsetHeight / this.list.length
		},
		listitemStyle() {
			return {
				height: `${ANCHOR_HEIGTH}px`,
				'line-height': `${ANCHOR_HEIGTH}px`
			}
		}
	},
	data() {
		return {
			activeIndex: 0,
			groupHeights: [],
			transformY: 0
		}
	},
	mounted() {
		this.init()
	},
	methods: {
		init() {
			const len = this.list.length
			let countHeight = 0
			for(let index = 0; index < len; index++) {
				const groupHeight = this.getHeight(index) + countHeight
				this.groupHeights.push(groupHeight)
				countHeight = groupHeight
			}
		},
		scroll({ y }) {
			y = Math.abs(y)

			for (let index = 0; index < this.len; index++) {
				const groupHeight = this.groupHeights[index]
				if (y < groupHeight) {
					this.activeIndex = index
					break
				}
			}

			const groupHeight = this.groupHeights[this.activeIndex]
			if ((groupHeight - y) < this.fixedTitleHeight) {
				this.transformY = groupHeight - y - this.fixedTitleHeight
			} else {
				this.transformY = 0
			}
		},
		getHeight(index) {
			const style = getComputedStyle(this.$refs[`group-${index}`][0])
			let height = style.height
			height = height.substr(0, height.length - 2)
			return parseFloat(height)
		},
		touchstart(e) {
			const { target, touches } = e
			let index = parseInt(target.getAttribute('data-index'))

			this.startY = touches[0].clientY
			this.startIndex = this.activeIndex

			this.scrollToIndex(index)
		},
		touchmove(e) {
			const touche = e.touches[0]
			let diff = (this.startY - touche.clientY) / this.sidebarItemHeight | 0
			this.scrollToIndex(this.startIndex - diff)
		},
		scrollToIndex(index) {
			if (isNaN(index)) return

			index = rangs(index, this.list.length - 1, 0)

			let height = this.groupHeights[index] + ANCHOR_HEIGTH

			let maxScrollY = Math.abs(this.$refs.scroll.scroll.maxScrollY)

			height = Math.min(maxScrollY, height)

			this.$refs.scroll.scrollTo(0, -height, 0)

			if (height !== maxScrollY) {
				this.activeIndex = index
			}
		},
		refresh() {
			this.$refs.scroll.refresh()
		},
		clickItem(item) {
			this.$emit('clickItem', item)
		}
	}
}
</script>
<style lang="less" scoped>
@import '~@/style/variable.less';
@import '~@/style/mixins.less';

.index-bar{
	position: relative;
	height: 100%;
	.index-bar__list{
		.index-bar__listitem{
			height: 30px;
			line-height: 30px;
			padding-left: 10px;
			padding-right: 35px;
		}
	}
	.index-bar__fixed{
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
	}
	.index-bar__title{
		display: block;
		height: 30px;
		line-height: 30px;
		background-color: white;
		font-size: @font-size-small;
		font-weight: bold;
		padding: 0 10px;
	}
	.index-bar__sidebar{
		position: absolute;
		right: 5px;
		top: 50%;
		transform: translateY(-50%);
		border-radius: 15px;
		background-color: #66666680;
		padding: 10px 0;
		width: 20px;
		text-align: center;
		.index-bar__sidebaritem{
			color: white;
			height: 15px;
			line-height: 15px;
		}
		.index-bar__sidebaritem--active{
			color: @primary-color;
		}
	}
}
</style>